package com.example.demo.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.demo.common.listener.ImportListener;
import com.example.demo.entity.User;
import com.example.demo.entity.pojo.BaseEntityPoJo;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import static org.apache.poi.ss.usermodel.BorderStyle.THIN;

/**
 * <!-- poi 相关-->
 *         <!--支持2003excel  -->
 *         <dependency>
 *             <groupId>org.apache.poi</groupId>
 *             <artifactId>poi</artifactId>
 *             <version>3.17</version>
 *         </dependency>
 *         <!--支持excel转成list  -->
 *         <dependency>
 *             <groupId>org.apache.poi</groupId>
 *             <artifactId>poi-ooxml-schemas</artifactId>
 *             <version>3.17</version>
 *         </dependency>
 *         <!--支持2007excel  -->
 *         <dependency>
 *             <groupId>org.apache.poi</groupId>
 *             <artifactId>poi-ooxml</artifactId>
 *             <version>3.17</version>
 *         </dependency>
 *         <!-- easy excel 2.1.7  -->
 *         <dependency>
 *             <groupId>com.alibaba</groupId>
 *             <artifactId>easyexcel</artifactId>
 *             <version>2.1.7</version>
 *         </dependency>
 */
@Slf4j
public class ExcelUtil {

    /**
     * 导出数据
     *
     * @param list  集合
     * @param path  路径
     * @param clazz 反射
     */
    public static <R extends BaseEntityPoJo, T extends BaseEntityPoJo> void writeWithHead(
            List<T> list, String path, Class<R> clazz) {
        isChartPathExist(path);//判断路径下是否有该文件，没有则创建该文件
        String pathName = path.replace("\\\\", "/");
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();//单元格样式
        headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE1.getIndex());
        // 这里 需要指定写用哪个class去写，然后写到第一个sheet，名字为模板，然后文件流会自动关闭
        // 如果这里想使用03，则传入excelType参数即可
        EasyExcel.write(pathName, clazz)
                //自适应列宽
                .registerWriteHandler(getHorizontalCellStyleStrategy())
                //设置sheet的名字
                .sheet("Sheet1")
                .doWrite(list);
    }

    /**
     * 导入数据
     *
     * @param file   文件
     * @param invoke invoke
     * @throws Exception 异常
     */
    //<T extends IService>声明T invoke是继承IService类的
    public static <T extends IService, E extends BaseEntityPoJo> List<E> readWithHead(
            MultipartFile file, final T invoke) throws Exception {
        log.info("readWithHead");
        InputStream inputStream = file.getInputStream();//将文件MultipartFile转化为InputStream流
        // 这里需要指定读用哪个class去读，然后读取第一个sheet
        //将InputStream流转化为list数组
        List<E> lists = EasyExcel.read(inputStream)
                // 注册监听器，可以在这里校验字段
                .registerReadListener(new ImportListener(invoke))//监听数据，写入时数据
                //表头
                .head(User.class)
                // 设置sheet,默认读取第一个
                .sheet()
                // 设置标题(表头)所在行数
                .headRowNumber(1)
                //doRead()和doReadSync()区别在于doReadSync()里面配了一个自定义的监听，并且返回读取到excel数据的List集合
                .doReadSync();
        return lists;
    }


    /**
     * 判断文件夹是否存在，如果不存在则新建
     *
     * @param dirPath 文件夹路径
     */
    private static void isChartPathExist(String dirPath) {
        File file = new File(dirPath);
        if (!file.exists()) {//file.exists()是否存在此文件
            // 先得到文件的上级目录，并创建上级目录，在创建文件夹
            file.getParentFile().mkdir();
            try {
                // 创建文件
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 用于设置excel导出时的样式
     */
    public static HorizontalCellStyleStrategy getHorizontalCellStyleStrategy() {
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景设置为白色
        headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE1.getIndex());
        // 字体大小
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 11);
        headWriteFont.setBold(false);
        headWriteCellStyle.setWriteFont(headWriteFont);

        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        contentWriteCellStyle.setBorderLeft(THIN);
        contentWriteCellStyle.setBorderTop(THIN);
        contentWriteCellStyle.setBorderRight(THIN);
        contentWriteCellStyle.setBorderBottom(THIN);

        // 这个策略 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    }
}
